package tool.view;

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.CheckBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.TextArea;
import javafx.stage.DirectoryChooser;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import tool.executor.LiteMaker;
import tool.executor.LiteMakerEvent;
import tool.executor.Packer;
import tool.executor.PackerEvent;
import tool.executor.UnpackEvent;
import tool.executor.Unpacker;
import tool.model.FilterSwitch;
import tool.model.MainModel;
import tool.util.JdbcUtil;


public class MainFX extends Application {
	
	@FXML private Button btnJre;
	@FXML private Button btnJar;
	@FXML private Button btnPkg;
	@FXML private Button btnExe;
	@FXML private ProgressBar progressBar;
	@FXML private TextArea text1;
	@FXML private CheckBox jfxBox;
	@FXML private CheckBox nioBox;
	@FXML private CheckBox awtBox;
	@FXML private ComboBox bundleMode;
	protected static boolean isTest = false;
	protected static boolean isUseFilter = true;
	protected static boolean noUnpack= false;
	protected static MainModel model;
	protected static FilterSwitch filterSwitch;
	protected String jreFloder;
	protected String jarFile;
	protected String buildFloder;
	protected ObservableList<String> modeList;
	private Stage stage;

	@SuppressWarnings("restriction")
	public static void main(String[] args) throws Exception {
		checkDB();
		if (args.length>0) {
			for (String string : args) {
				if(string.equals("-t")){
					isTest=true;
				}
				if(string.equals("-nf")){
					isUseFilter=false;
				}
				if(string.equals("-npk")){
					noUnpack=true;
				}
			}
		}
		model = new MainModel();
		filterSwitch = new FilterSwitch();
        launch(args);
    }

	private static void checkDB() {
		JdbcUtil jdbcUtil = new JdbcUtil();
		List<Map<String, Object>> filterList = jdbcUtil.queryForList("SELECT count(*) CC FROM sqlite_master WHERE type='table' AND name='filter'");
		if(filterList.size()>0 && filterList.get(0).get("CC").equals(0)) {
			jdbcUtil.createDefTable();
		}
	}

	@SuppressWarnings("restriction")
	public void start(Stage stage) throws Exception {


        String fxmlFile = "/fxml/main.fxml";
        FXMLLoader loader = new FXMLLoader();
        Parent rootNode = (Parent) loader.load(getClass().getResourceAsStream(fxmlFile));

        Scene scene = new Scene(rootNode, 602, 302);
        //scene.getStylesheets().add("/styles/styles.css");

        stage.setTitle("JRE精简程序");
        stage.setScene(scene);
        stage.show();
        this.stage = stage;
        MainFX controller = loader.<MainFX>getController();
        controller.loaded();
    }
	
	@SuppressWarnings("restriction")
	@FXML private void btnJre_onClick(){
		folderDig(stage);
	}
	@SuppressWarnings("restriction")
	@FXML private void btnJar_onClick(){
		fileDig(stage);
		if(!jreFloder.isEmpty() && !jarFile.isEmpty()){
			model.setExecutable(true);
			btnPkg.setDisable(!model.getExecutable());
		}
	}
	@SuppressWarnings("restriction")
	@FXML private void btnPkg_onClick(){
		//精简rt.jar
		workflow();
	}
	@SuppressWarnings("restriction")
	@FXML private void btnExe_onClick(){
		//精简jre文件夹
		workflowForLite();
	}
	@SuppressWarnings("restriction")
	@FXML private void jfxBox_onClick(){
		filterSwitch.setEnableJavaFX(jfxBox.isSelected());
	}
	@SuppressWarnings("restriction")
	@FXML private void nioBox_onClick(){
		filterSwitch.setEnableNio(nioBox.isSelected());
	}
	@SuppressWarnings("restriction")
	@FXML private void awtBox_onClick(){
		filterSwitch.setEnableAWT(awtBox.isSelected());
	}
	
	@SuppressWarnings("restriction")
	private void loaded(){
		btnPkg.setDisable(true);
		btnExe.setDisable(true);
		jfxBox.setSelected(filterSwitch.isEnableJavaFX());
		modeList = FXCollections.observableArrayList (
			    "桌面图形界面程序", "命令行程序", "WEB项目", "微服务"); 
		bundleMode.setItems(modeList);
		bundleMode.getSelectionModel().select(0);
	}
	
	@SuppressWarnings("restriction")
	private void println(String line) {
		text1.setText(line);
	}
	
	@SuppressWarnings("restriction")
	private void fileDig(Stage stage) {
		FileChooser fileChooser = new FileChooser();
		File file = fileChooser.showOpenDialog(stage);
		if (file != null) {
			this.jarFile = file.getAbsolutePath();
			System.out.println(this.jarFile);
		}
	}
	@SuppressWarnings("restriction")
	private void folderDig(Stage stage) {
		DirectoryChooser folderChooser = new DirectoryChooser();
		File file = folderChooser.showDialog(stage);
		if (file != null) {
			
			//TODO 需要用户选择jdk下的jre文件夹
			String canonicalPath = "";
			try {
				canonicalPath = file.getParentFile().getCanonicalPath();
			} catch (Exception e1) {
				alert(stage,"请你选择jdk下的jre文件夹！");
				return;
			}
			
			String javac = canonicalPath+File.separator+"bin"+File.separator+"javac";
			try {
				Process p = Runtime.getRuntime().exec(javac);
			} catch (IOException e) {
				alert(stage,"请你选择jdk下的jre文件夹！");
				return;
			}
			this.jreFloder = file.getAbsolutePath();
			System.out.println(this.jreFloder);
		}
	}

	private void alert(Stage stage,String content) {
		Alert alert = new Alert(Alert.AlertType.INFORMATION);
		alert.setTitle("信息");
		alert.setHeaderText("");
		alert.setContentText(content);
		alert.initOwner(stage);
		alert.show();
	}
	
	/**
	 * 工作流
	 */
	private void workflow() {
		if (model.getInProgress()) {
			//不准重叠运行
			return;
		}
		model.setInProgress(true);
		int selectedIndex = bundleMode.getSelectionModel().getSelectedIndex();
		model.setMode(selectedIndex);
		//准备目录
		buildFloder = new File("."+File.separator).getAbsolutePath()+"\\build";
		//准备事件
		UnpackEvent uevent = new UnpackEvent() {
			
			@Override
			public void generateDone() {
				@SuppressWarnings("restriction")
				Thread th = new Thread(()-> {
					while (!model.getUnpackOkey()) {
						try {
							Thread.sleep(1000);
						} catch (InterruptedException e) {
							Platform.runLater(() -> {
								println(e.getMessage());
							});
						}
					}
					 Platform.runLater(() -> {
						 println("分析完成,开始提取...");
					        progressBar.setProgress(0.4);
					 });
					Unpacker.deleteFiles(model,this,isTest,isUseFilter,filterSwitch);
				});
				th.start();
			}
			
			@Override
			public void exDone() {
				Platform.runLater(() -> {
					println("提取完成.");
					progressBar.setProgress(0.2);
				});
				model.setUnpackOkey(true);
			}
			
			@Override
			public void delDone() {
				Platform.runLater(() -> {
					println("拆包完成.");
					progressBar.setProgress(0.6);
				});
				Packer packer = new Packer(new PackerEvent() {
					
					@Override
					public void addOne(String row) {
						Platform.runLater(() -> {
							println(row);
						});
					}
					
					@Override
					public void addDone(String jarFileName) {
						Platform.runLater(() -> {
							println("生成"+jarFileName+"完成.");
							progressBar.setProgress(1);
							btnExe.setDisable(false);
						});
						model.setInProgress(false);
					}
				});
				packer.packJar(jreFloder, "rt.jar",buildFloder);
			}
		};
		
		//流程
		println("正在生成ClassList");
		Unpacker.generateClassList(jreFloder, jarFile,model,uevent);
		progressBar.setProgress(0.1);
		if (!noUnpack) {
			println("正在提取核心包，程序当前目录会出现很多文件夹，请不要手动删除！");
			Unpacker.unpack(jreFloder,uevent,buildFloder);
		}else{
			model.setUnpackOkey(true);
		}
	}
	
	/**
	 * 精简JRE目录流程
	 */
	private void workflowForLite() {
		// 启动精简
		if (model.getInProgress()) {
			return;
		}
		model.setInProgress(true);
		
		progressBar.setProgress(0.1);
		println("正在执行精简...");
		//准备事件
		LiteMakerEvent levent = new LiteMakerEvent() {
			@Override
			public void done() {
				Platform.runLater(() -> {
					progressBar.setProgress(1);
					println("精简完成,请打开你选择JRE文件夹查看它的大小吧！");
				});
				model.setInProgress(false);
			}

			@Override
			public void scanDone() {
				Platform.runLater(() -> {
					progressBar.setProgress(0.4);
					println("扫描目录完成");
				});
			}

			@Override
			public void deleteStart(String path) {
				Platform.runLater(() -> {
					progressBar.setProgress(0.8);
					println("开始删除文件:"+path);
				});
			}

			@Override
			public void copyError(Exception e) {
				Platform.runLater(() -> {
					progressBar.setProgress(1);
					println("复制精简后的jar文件错误:"+e.getMessage());
				});
			}
		};
		LiteMaker.doLite(jreFloder,buildFloder,model,filterSwitch,isTest,levent);

	}
}
